import os
import json
import random
import string
import time

Debug = False

# 创建必要的文件和文件夹
if not os.path.exists("config.json"):
    with open("config.json", "w", encoding='utf-8') as file:
        now_path = os.getcwd()
        config = {
            "dailysPath" :os.path.join(now_path,"dailys"),
            "decodedPath":os.path.join(now_path,"decoded"),
            "originPath" :os.path.join(now_path,"origin"),
            "bookPath"   :os.path.join(now_path,"book.json"),
        }
        file.write(json.dumps(config))
        

def getConfig(configPath:str = "./config.json") -> dict:
    with open(configPath,"r") as f:
        return json.load(f)
    
config:dict = getConfig()

if not os.path.exists(config['bookPath']):
    with open(config['bookPath'], "w", encoding='utf-8') as file:
        file.write("{}")

if not os.path.exists(config['dailysPath']):
    os.mkdir(config['dailysPath'])
if not os.path.exists(config['originPath']):
    os.mkdir(config['originPath'])
if not os.path.exists(config['decodedPath']):
    os.mkdir(config['decodedPath'])


def createRandomString(length=10,seed=time.localtime()) -> str:
    """生成给定长度的随机字符串【0-9,A-Z,a-z,所有符号】

    Args:
        length (int, optional): 生成的字符串长度. Defaults to 10.

    Returns:
        str: 字符串
    """
    random.seed(seed)
    characters = string.ascii_letters + string.digits + string.punctuation
    result = ''.join(random.choice(characters) for _ in range(length))
    return result


def decodeByBook(txt: str, book: dict, codeLength: int = 10) -> str:
    """通过密码本解密文本

    Args:
        txt (str): 密文
        book (dict): 密码本
        codeLength (int, optional): 密码文本长度. Defaults to 10.

    Returns:
        str: 解密后的原文
    """
    res: str = ""
    temp_txt: str = ""
    book = {value: key for key, value in book.items()}
    for char in txt:
        temp_txt += char
        if len(temp_txt) == codeLength:
            res += book[temp_txt]
            temp_txt = ""

    return res

# 解密


def decodeDaily(dailyPath: str, bookPath: str = config['bookPath']) -> None:
    """解密Daily文件

    Args:
        dailyPath (str): daily文件路径
        bookPath (str, optional): 秘密本文件路径. Defaults to config['bookPath'].
    """
    book: dict = readBook(bookPath)
    origin_txt: str = ""
    with open(dailyPath, "r", encoding='utf-8') as file:
        origin_txt = file.read()

    fileName = os.path.join(config["decodedPath"],time.strftime("%Y-%m-%d_%H_%M", time.localtime()) + ".txt")

    with open(fileName, "w", encoding='utf-8') as file:
        file.write(decodeByBook(origin_txt, book))


def encodeByBook(txt: str, book: dict) -> str:
    """通过密码本加密文本

    Args:
        txt (str): 原文
        book (dict): 密码本

    Returns:
        str: 加密后的密文
    """
    res = ""
    for char in txt:
        res += book[char]
    return res

# 加密


def encodeDaily(originPath: str, bookPath: str = config['bookPath']) -> None:
    """加密文本,生成daily文件

    Args:
        originPath (str): 原文路径
        bookPath (str, optional): 密码本路径. Defaults to config['bookPath'].
    """
    book: dict = readBook(bookPath)
    daily_txt: str = ""
    with open(originPath, "r", encoding='utf-8') as file:
        daily_txt = file.read()

    for char in daily_txt:
        keys = book.keys()

        # 没有找到对应的值
        if char not in keys:
            new_value: str = createRandomString(10,seed=char+"cc123hh")

            while new_value in book.values():
                new_value = createRandomString(10,seed=char+"cc123hh")

            book[char] = new_value
    if Debug:
        for key in book.keys():
            print(f"{key} => {book[key]}")

    # 保存daily
    fileName = os.path.join(config['dailysPath'],time.strftime("%Y-%m-%d_%H_%M", time.localtime()) + ".daily")
    with open(fileName, "w", encoding='utf-8') as daily_file:
        daily_file.write(encodeByBook(daily_txt, book))

    # 保存book
    with open(bookPath, "w", encoding='utf-8') as file:
        file.write(json.dumps(book))


def readBook(bookPath: str = config['bookPath']) -> dict:
    """读取密码本

    Args:
        bookPath (str, optional): 密码本路径. Defaults to config['bookPath'].

    Returns:
        dict: 密码本
    """
    dic: dict = {}

    with open(bookPath, "r", encoding='utf-8') as file:
        dic = json.loads(file.read())

    return dic


def getOriginDailyList() -> dict:
    """获取原文文件夹的文件目录

    Returns:
        dict: 原文文件目录
    """
    origin: list = os.listdir(config["originPath"])
    origin_dic: dict = {}

    for i in range(1, len(origin)+1):
        origin_dic[i] = {
            "filePath": os.path.join(config["originPath"],origin[i-1]),
            "fileName": origin[i-1],
            "Index": i
        }

    return origin_dic


def getDailyList() -> dict:
    """获取daily文件夹的文件目录

    Returns:
        dict: daily文件目录
    """
    origin: list = os.listdir(config['dailysPath'])
    origin_dic: dict = {}

    for i in range(1, len(origin)+1):
        origin_dic[i] = {
            "filePath": os.path.join(config['dailysPath'],origin[i-1]),
            "fileName": origin[i-1],
            "Index": i
        }

    return origin_dic


def encode_func() -> None:
    """加密方法
    """
    org_dic: dict = getOriginDailyList()
    if len(org_dic)==0:
        print("没有找到原文文件")
        return
    for key in org_dic.keys():
        print(f"{key} : {org_dic[key]}")

    dailyIndex: int = int(input("输入要打开的文件代码："))

    encodeDaily(org_dic[dailyIndex]['filePath'])


def decode_func() -> None:
    """解密方法
    """
    daily_dic: dict = getDailyList()
    if len(daily_dic)==0:
        print("没有找到dailys文件")
        return
    for key in daily_dic.keys():
        print(f"{key} : {daily_dic[key]}")

    dailyIndex: int = int(input("输入要打开的文件代码："))

    decodeDaily(daily_dic[dailyIndex]['filePath'])


def GoExit() -> None:
    """退出函数
    """
    print("bye")
    exit()


while True:

    print("[0] 退出\n[2] 加密\n[3] 解密\n")

    code: int = int(input("Code:"))

    func_dict = {
        0: GoExit,
        2: encode_func,
        3: decode_func,
    }

    func_dict[code]()
